package us.mooresr.webtroopmanager.client.ui;

import java.util.ArrayList;
import java.util.List;

import us.mooresr.webtroopmanager.client.place.EventListPlace;
import us.mooresr.webtroopmanager.client.ui.cells.DriverCell;
import us.mooresr.webtroopmanager.client.ui.cells.PersonCell;
import us.mooresr.webtroopmanager.client.ui.cells.VehicleCell;
import us.mooresr.webtroopmanager.shared.EventDriverSummary;
import us.mooresr.webtroopmanager.shared.PersonSummary;
import us.mooresr.webtroopmanager.shared.Privilege;
import us.mooresr.webtroopmanager.shared.VehicleSummary;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;

public class EventDriversViewImpl extends Composite implements EventDriversView {

	private static EventDriversViewImplUiBinder uiBinder = GWT
			.create(EventDriversViewImplUiBinder.class);

	interface EventDriversViewImplUiBinder extends
			UiBinder<Widget, EventDriversViewImpl> {
	}
	
	private Presenter presenter;
	
	private ListDataProvider<PersonSummary> leftListProvider;
	private CellList<PersonSummary> personList;
	
	private ListDataProvider<VehicleSummary> rightListProvider;
	private CellList<VehicleSummary> vehicleList;
	
	private ListDataProvider<EventDriverSummary> bottomListProvider;
	private CellList<EventDriverSummary> driverList;
	
	private PersonSummary selectedPerson;
	private VehicleSummary selectedVehicle;
	private EventDriverSummary selectedDriver;
	
	@UiField
	Button okButton;
	
	@UiField
	Button cancelButton;
	
	@UiField
	Button addButton;
	
	@UiField
	Button removeButton;
	
	@UiField
	ScrollPanel leftScroller;
	
	@UiField
	ScrollPanel rightScroller;
	
	@UiField
	ScrollPanel bottomScroller;
	
	@UiHandler("okButton")
	void onOK(ClickEvent e) {
		List<EventDriverSummary> drivers = bottomListProvider.getList();
		
		// For some reason we can't serialize the list we get from the data provider
		ArrayList<EventDriverSummary> serializableList = new ArrayList<EventDriverSummary>();
		for (EventDriverSummary ed : drivers) {
			serializableList.add(ed);
		}
		
		presenter.storeEventDrivers(serializableList);
		
		presenter.goTo(new EventListPlace());
	}
	
	@UiHandler("cancelButton")
	void onCancel(ClickEvent e) {
		presenter.goTo(new EventListPlace());
	}
	
	@UiHandler("addButton")
	void onAdd(ClickEvent e) {
		String description;
		
		description = selectedPerson.toString() + " driving " + selectedVehicle.toString();
		
		EventDriverSummary newDriver = new EventDriverSummary(null, presenter.getEventId(), selectedVehicle.getId(),
				selectedPerson.getId(), description);
		
		// Add the new driver to the driver list
		List<EventDriverSummary> driverNames = bottomListProvider.getList();
		driverNames.add(newDriver);
		driverList.setPageSize(driverNames.size());
		driverList.getSelectionModel().setSelected(newDriver, false);
		
		// Remove the person from the list of people
		personList.getSelectionModel().setSelected(selectedPerson, false);
		List<PersonSummary> peopleNames = leftListProvider.getList();
		peopleNames.remove(selectedPerson);
		personList.setPageSize(peopleNames.size());
		selectedPerson = null;
		selectedPersonChanged();
		
		// Remove the vehicle from the list of vehicles
		vehicleList.getSelectionModel().setSelected(selectedVehicle, false);
		List<VehicleSummary> vehicleNames = rightListProvider.getList();
		vehicleNames.remove(selectedVehicle);
		vehicleList.setPageSize(vehicleNames.size());
		selectedVehicle = null;
		selectedVehicleChanged();
		
		
		
		
	}
	
	@UiHandler("removeButton")
	void onRemove(ClickEvent e) {
		
		// Remove the driver from the driver list
		driverList.getSelectionModel().setSelected(selectedDriver, false);
		List<EventDriverSummary> driverNames = bottomListProvider.getList();
		driverNames.remove(selectedDriver);
		driverList.setPageSize(driverNames.size());
		selectedDriver = null;
		selectedDriverChanged();

		
		// Have the presenter refresh the people and vehicle lists
		presenter.refreshLists();
		
	}

	public EventDriversViewImpl() {
		initWidget(uiBinder.createAndBindUi(this));
		
		// The left scroller contains a list of people
		
		ProvidesKey<PersonSummary> personKeyProvider = new ProvidesKey<PersonSummary>() {
			public Object getKey(PersonSummary item) {
				return (item == null) ? null : item.getId();
			}
		};
		
		personList = new CellList<PersonSummary>(new PersonCell(), personKeyProvider);
		personList.setSize("147px", "300px");
		
		final SingleSelectionModel<PersonSummary> personSelectionModel = 
			new SingleSelectionModel<PersonSummary>(personKeyProvider);
		personList.setSelectionModel(personSelectionModel);
		personSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				selectedPerson = personSelectionModel.getSelectedObject();
				selectedPersonChanged();		
			}			
		});
		
		leftScroller.setWidget(personList);
		
		leftListProvider = new ListDataProvider<PersonSummary>();
		leftListProvider.addDataDisplay(personList);
		
		
		// The right scroller contains a list of vehicles
		
		ProvidesKey<VehicleSummary> vehicleKeyProvider = new ProvidesKey<VehicleSummary>() {
			public Object getKey(VehicleSummary item) {
				return (item == null) ? null : item.getId();
			}
		};
		
		vehicleList = new CellList<VehicleSummary>(new VehicleCell(), vehicleKeyProvider);
		vehicleList.setSize("147px", "300px");
		
		final SingleSelectionModel<VehicleSummary> vehicleSelectionModel = 
			new SingleSelectionModel<VehicleSummary>(vehicleKeyProvider);
		vehicleList.setSelectionModel(vehicleSelectionModel);
		vehicleSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				selectedVehicle = vehicleSelectionModel.getSelectedObject();
				selectedVehicleChanged();		
			}			
		});
		
		rightScroller.setWidget(vehicleList);
		
		rightListProvider = new ListDataProvider<VehicleSummary>();
		rightListProvider.addDataDisplay(vehicleList);
		
		// The bottom scroller contains drivers (pairs of people and vehicles)
		
		ProvidesKey<EventDriverSummary> driverKeyProvider = new ProvidesKey<EventDriverSummary>() {
			public Object getKey(EventDriverSummary item) {
				return (item == null) ? null : item.toString();
			}
		};
		
		driverList = new CellList<EventDriverSummary>(new DriverCell(), driverKeyProvider);
		driverList.setSize("300px", "100px");
		
		final SingleSelectionModel<EventDriverSummary> driverSelectionModel = 
			new SingleSelectionModel<EventDriverSummary>(driverKeyProvider);
		driverList.setSelectionModel(driverSelectionModel);
		driverSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				selectedDriver = driverSelectionModel.getSelectedObject();
				selectedDriverChanged();		
			}			
		});
		
		bottomScroller.setWidget(driverList);
		
		bottomListProvider = new ListDataProvider<EventDriverSummary>();
		bottomListProvider.addDataDisplay(driverList);
		
		// Initially disable the buttons.  They're enabled when the correct list items are selected
		addButton.setEnabled(false);
		removeButton.setEnabled(false);
		
	}
	
	protected void selectedDriverChanged() {
		if (selectedDriver == null) {
			removeButton.setEnabled(false);
		} else {
			if (presenter.isAllowed(Privilege.REMOVE_DRIVER_FROM_EVENT, selectedDriver.getVehicleId())) {
				removeButton.setEnabled(true);
			} else {
				removeButton.setEnabled(false);
			}
		}
		
	}

	protected void selectedVehicleChanged() {
		if ((selectedPerson != null) && (selectedVehicle != null)) {
			if (presenter.isAllowed(Privilege.ADD_DRIVER_TO_EVENT, selectedPerson.getId())) {
				addButton.setEnabled(true);
			} else {
				addButton.setEnabled(false);
			}
			addButton.setEnabled(true);
		} else {
			addButton.setEnabled(false);
		}
		
	}

	protected void selectedPersonChanged() {
		if ((selectedPerson != null) && (selectedVehicle != null)) {
			if (presenter.isAllowed(Privilege.ADD_DRIVER_TO_EVENT, selectedPerson.getId())) {
				addButton.setEnabled(true);
			} else {
				addButton.setEnabled(false);
			}
		} else {
			addButton.setEnabled(false);
		}
		
	}


	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
		
	}

	@Override
	public void setInitialDrivers(List<EventDriverSummary> drivers) {
		List<EventDriverSummary> providerList = bottomListProvider.getList();
		providerList.clear();
		for (EventDriverSummary d : drivers) {
			providerList.add(d);
		}
		driverList.setPageSize(drivers.size());
		selectedDriver = null;
		selectedDriverChanged();
		
	}

	@Override
	public void setInitialPeople(List<PersonSummary> people) {
		List<EventDriverSummary> driverSummaryList = bottomListProvider.getList();
		
		List<PersonSummary> providerList = leftListProvider.getList();
		providerList.clear();
		
		Boolean skipThis;
		for (PersonSummary p : people) {
			// If this person is on the driver list don't add him
			skipThis = false;
			for (EventDriverSummary ed : driverSummaryList) {
				if (ed.getPersonId().equals(p.getId())) {
					skipThis = true;
					break;
				}
			}
			if (!skipThis) {
				providerList.add(p);
			}
		}
		personList.setPageSize(people.size());
		selectedPerson = null;
		selectedPersonChanged();
		
	}

	@Override
	public void setInitialVehicles(List<VehicleSummary> vehicles) {
		List<EventDriverSummary> driverSummaryList = bottomListProvider.getList();
		
		List<VehicleSummary> providerList = rightListProvider.getList();
		providerList.clear();
		
		Boolean skipThis;
		for (VehicleSummary v : vehicles) {
			// If this vehicle is on the driver list don't add it
			skipThis = false;
			for (EventDriverSummary ed : driverSummaryList) {
				if (ed.getVehicleId().equals(v.getId())) {
					skipThis = true;
					break;
				}
			}
			if (!skipThis) {
				providerList.add(v);
			}
		}
		vehicleList.setPageSize(vehicles.size());
		selectedVehicle = null;
		selectedVehicleChanged();
		
		
	}

}
